home *** CD-ROM | disk | FTP | other *** search
/ BCI NET / BCI NET Dec 94.iso / archives / applications / wp / ged11.lha / Install / data / main / GoldED / API / rexx / main.c next >
C/C++ Source or Header  |  1994-08-12  |  12KB  |  406 lines

  1. /* -----------------------------------------------------------------------------
  2.  
  3.  GoldED API client example code, ©1994 Dietmar Eilert. Dice:
  4.  
  5.  dcc main.c -// -mRR -r -proto -2.0 -o ram:rexx
  6.  
  7.  The following code demonstrates how to  add  additional  internal  commands  to
  8.  GoldED  using  a  client. After having installed this client using GoldED's API
  9.  requester you may use the following additional commands within menus, macros or
  10.  in the command requester:
  11.  
  12.     o DISPLAYBEEP (flash screen)
  13.     o ABOUT
  14.  
  15.  The following  example  uses  synchronous  ARexx  communication:  Requests  are
  16.  PutMsg()'ed  to  GoldED's  port,  followed  by a WaitPort() to get the editor's
  17.  response. This works fine since we need no ARexx communication  after  the  API
  18.  link has been established. If there were ARexx communication AFTER the link has
  19.  been established (i.e. after sending the 'API  PORT=...'  command  to  register
  20.  with  GoldED),  we  would  have to use an asynchronous design beeing capable of
  21.  answering incoming API messages while waiting for completion of ARexx  requests
  22.  sent to GoldED.
  23.  
  24.  FRANÇAIS
  25.  
  26.  Le code suivant montre comment ajouter des commandes internes supplémentaires à
  27.  GoldED,  en utilisant un client. Après avoir installé ce client en utilisant la
  28.  requête API de GoldED, vous pouvez utiliser une des  commandes  supplémentaires
  29.  suivantes dans les menus, les macros ou dans la requête de commande:
  30.  
  31.      o DISPLAYBEEP (flasher l'écran)
  32.      o ABOUT
  33.  
  34.  Cet exemple  utilise  la  communication  ARexx  synchrone:  les  requêtes  sont
  35.  PutMsg()'ées  sur  le  port  de  GoldED,  suivies d'un WaitPort() pour avoir la
  36.  réponse de l'éditeur. Ceci fonctionne très bien comme nous n'avons  pas  besoin
  37.  de  communications  ARexx  après l'établissement de la liaison API (c-à-d après
  38.  l'envoi de la commande  'API  PORT=...'  pour  s'enregistrer  à  GoldED),  nous
  39.  aurions  dû  utiliser  un  système  asynchrone  étant  capable  de répondre aux
  40.  messages API arrivants, tout en attendant la fin des requêtes ARexx envoyées  à
  41.  GoldED.
  42.  
  43.   ------------------------------------------------------------------------------
  44. */
  45.  
  46. /// "includes"
  47.  
  48. #define Prototype extern
  49.  
  50. #include <exec/exec.h>
  51. #include <string.h>
  52. #include <stdio.h>
  53. #include <stdlib.h>
  54. #include <dos/dos.h>
  55. #include <dos/rdargs.h>
  56. #include <intuition/intuition.h>
  57. #include <rexx/errors.h>
  58. #include <rexx/rxslib.h>
  59. #include <utility/tagitem.h>
  60. #include <clib/exec_protos.h>
  61. #include <clib/dos_protos.h>
  62. #include <clib/intuition_protos.h>
  63. #include <clib/rexxsyslib_protos.h>
  64.  
  65. #include "golded:api/include/golded.h"
  66.  
  67. Prototype void   main(int, char **);
  68. Prototype void   HandleAPI(char *);
  69. Prototype void   Dispatch(struct APIMessage *);
  70. Prototype ULONG *SendRexxCommand(char *, char *, struct MsgPort *, char *);
  71. Prototype LONG   CommandBeep (ULONG *, struct APIMessage *);
  72. Prototype LONG   CommandAbout(ULONG *, struct APIMessage *);
  73.  
  74. ///
  75. /// "main"
  76.  
  77. void
  78. main(int argc, char **argv)
  79. {
  80.     const char *version = "$VER: rexx 1.3 (" __COMMODORE_DATE__ ")";
  81.  
  82.     if (argc == 2)
  83.         HandleAPI(argv[1] + 5);
  84.     else
  85.         puts("syntax error: rexx HOST=<host>");
  86.  
  87.     exit(0);
  88. }
  89.  
  90. ///
  91. /// "API management"
  92.  
  93. /* --------------------------------- HandleAPI ---------------------------------
  94.  
  95.  Register with GoldED & handle incoming API messages.
  96.  
  97.  S'enregistrer à GoldED & gérer les messages API arrivants.
  98.  
  99. */
  100.  
  101. void
  102. HandleAPI(host)
  103.  
  104. char *host;
  105. {
  106.     struct MsgPort *replyPort;
  107.  
  108.     if (replyPort = CreateMsgPort()) {
  109.  
  110.         char  command[255];
  111.         ULONG *result;
  112.  
  113.         sprintf(command, "API PORT=%ld MASK=%ld", replyPort, API_CLASS_ROOT | API_CLASS_REXX);
  114.  
  115.         if (result = SendRexxCommand(host, command, replyPort, NULL)) {
  116.  
  117.             if (*result == RC_OK) {
  118.  
  119.                 BOOL active = TRUE;
  120.  
  121.                 do {
  122.  
  123.                     struct APIMessage *apiMsg, *nextMsg;
  124.  
  125.                     // API messages might already have arrived since SendRexxCommand() only pulls one message of the port
  126.  
  127.                     while (!(apiMsg = (struct APIMessage *)GetMsg(replyPort)))
  128.                         WaitPort(replyPort);
  129.  
  130.                     do {
  131.  
  132.                         for (nextMsg = apiMsg; nextMsg; nextMsg = nextMsg->api_Next) {
  133.  
  134.                             if (nextMsg->api_State == API_STATE_NOTIFY) {
  135.  
  136.                                 switch (nextMsg->api_Class) {
  137.  
  138.                                     case API_CLASS_ROOT:
  139.  
  140.                                         switch (nextMsg->api_Action) {
  141.  
  142.                                             case API_ACTION_DIE:
  143.  
  144.                                                 active = FALSE;
  145.                                                 break;
  146.  
  147.                                             case API_ACTION_INTRODUCE:
  148.  
  149.                                                 static struct TagItem tags[] = {
  150.  
  151.                                                     API_Client_Name,      "rexx",
  152.                                                     API_Client_Copyright, "©1994 Dietmar Eilert",
  153.                                                     API_Client_Purpose,   "API client example code",
  154.                                                     API_Client_Template,  "DISPLAYBEEP",
  155.                                                     API_Client_Template,  "ABOUT",
  156.                                                     TAG_DONE
  157.                                                 };
  158.  
  159.                                                 nextMsg->api_Data = tags;
  160.                                                 break;
  161.  
  162.                                             default:
  163.  
  164.                                                 nextMsg->api_Error = API_ERROR_UNKNOWN;
  165.                                         }
  166.  
  167.                                         break;
  168.  
  169.                                     case API_CLASS_REXX:
  170.  
  171.                                         switch (nextMsg->api_Action) {
  172.  
  173.                                             case API_ACTION_COMMAND:
  174.  
  175.                                                 Dispatch(nextMsg);
  176.                                                 break;
  177.  
  178.                                             default:
  179.  
  180.                                                 nextMsg->api_Error = API_ERROR_UNKNOWN;
  181.                                         }
  182.                                         break;
  183.  
  184.                                     default:
  185.  
  186.                                         nextMsg->api_Error = API_ERROR_UNKNOWN;
  187.                                 }
  188.                             }
  189.                         }
  190.  
  191.                         ReplyMsg((struct Message *)apiMsg);
  192.  
  193.                     } while (apiMsg = (struct APIMessage *)GetMsg(replyPort));
  194.  
  195.                 } while (active);
  196.             }
  197.         }
  198.  
  199.         DeleteMsgPort(replyPort);
  200.     }
  201. }
  202.  
  203.  
  204. ///
  205. /// "dispatcher"
  206.  
  207. /* --------------------------------- Dispatch ----------------------------------
  208.  
  209.  Dispatch incoming command: examine command string (command part is uppercase
  210.  already), look for handler function related to command, parse arguments (if 
  211.  command supports arguments), call handler.
  212.  
  213.  Dispatcher les commandes arrivants: examiner la chaîne de la commande (la
  214.  partie commande est déjà en majuscules), rechercher des fonctions de gestion se
  215.  rapportant à la commande, analyser les arguments (si la commande gère des
  216.  arguments), appeler le gestionnaire.
  217.  
  218. */
  219.  
  220. void
  221. Dispatch(apiMsg)
  222.  
  223. struct APIMessage *apiMsg;
  224. {
  225.     struct RDArgs *rdArgs, *args;
  226.  
  227.     if (rdArgs = AllocDosObject(DOS_RDARGS, NULL)) {
  228.  
  229.         static char buffer[1024];
  230.  
  231.         // table of supported commands, associated handlers & template strings
  232.         // table des commandes gérées, chaînes des handlers & template associées
  233.  
  234.         static struct parser { char *command; LONG (*handler)(ULONG *, struct APIMessage *); char *template; } parser[] = {
  235.  
  236.             "DISPLAYBEEP",  (APTR)CommandBeep,  NULL,
  237.             "ABOUT",        (APTR)CommandAbout, NULL,
  238.              NULL
  239.         };
  240.  
  241.         ULONG n, argArray[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  242.  
  243.         struct APIRexxNotify *notify = (struct APIRexxNotify *)apiMsg->api_Data;
  244.  
  245.         // make LF-terminated copy of command string (required by dos/readArgs):
  246.         // créer une copie terminée par LF de la chaîne de commande (requise par dos/readArgs):
  247.  
  248.         strcpy(buffer, notify->arn_Command);
  249.         strcat(buffer, "\12");
  250.  
  251.         for (n = 0; parser[n].command; ++n) {
  252.  
  253.             if (!memcmp(buffer, parser[n].command, strlen(parser[n].command))) {
  254.  
  255.                 // tell GoldED that message has been consumed by us:
  256.                 // Dire à GoldED que le message a été utilisé par nous:
  257.  
  258.                 apiMsg->api_State = API_STATE_CONSUMED;
  259.  
  260.                 char *arguments = buffer + strlen(parser[n].command);
  261.  
  262.                 rdArgs->RDA_Source.CS_Buffer = arguments;
  263.                 rdArgs->RDA_Source.CS_Length = strlen(arguments);
  264.                 rdArgs->RDA_Source.CS_CurChr = 0;
  265.                 rdArgs->RDA_DAList           = NULL;
  266.                 rdArgs->RDA_Buffer           = NULL;
  267.  
  268.                 if (parser[n].template) {
  269.  
  270.                     if (args = ReadArgs(parser[n].template, argArray, rdArgs)) {
  271.  
  272.                         notify->arn_RC = (*parser[n].handler)(argArray, apiMsg);
  273.  
  274.                         FreeArgs(args);
  275.                     }
  276.                     else {
  277.  
  278.                         static char errorText[81];
  279.  
  280.                         notify->arn_RC           = RC_WARN;
  281.                         notify->arn_CommandError = errorText;
  282.  
  283.                         Fault(IoErr(), "IoErr()", errorText, 80);
  284.                     }
  285.                 }
  286.                 else
  287.                     notify->arn_RC = (*parser[n].handler)(argArray, apiMsg);
  288.             }
  289.         }
  290.  
  291.         FreeDosObject(DOS_RDARGS, rdArgs);
  292.     }
  293. }
  294.  
  295. /* -------------------------------- CommandBeep --------------------------------
  296.  
  297.  DISPLAYBEEP
  298.  
  299. */
  300.  
  301. LONG
  302. CommandBeep(argArray, apiMsg)
  303.  
  304. ULONG  *argArray;
  305. struct APIMessage *apiMsg;
  306. {
  307.     DisplayBeep(0);
  308.  
  309.     return(RC_OK);
  310. }
  311.  
  312. /* ------------------------------- CommandAbout --------------------------------
  313.  
  314.  ABOUT (open a requester on GoldED's screen)
  315.  ABOUT (ouvre une requête sur l'écran GoldED)
  316.  
  317. */
  318.  
  319. LONG
  320. CommandAbout(argArray, apiMsg)
  321.  
  322. ULONG  *argArray;
  323. struct APIMessage *apiMsg;
  324. {
  325.     struct EasyStruct about = {sizeof(struct EasyStruct), 0, "Info", "Just some API client example code", "OK" };
  326.  
  327.     EasyRequestArgs(apiMsg->api_WinInfo->Window, &about, NULL, NULL);
  328.  
  329.     return(RC_OK);
  330. }
  331.  
  332.  
  333. ///
  334. /// "ARexx"
  335.  
  336. /* ---------------------------------- SendRexxCommand -------------------------
  337.  
  338.  Send ARexx message & wait for answer. Return pointer to result or NULL.
  339.  
  340.  Envoyer une commande ARexx et attendre une réponse. Retourne un pointeur sur le
  341.  résultat ou NULL.
  342.  
  343. */
  344.  
  345. ULONG *
  346. SendRexxCommand(port, cmd, replyPort, buffer)
  347.  
  348. char   *cmd, *port, *buffer;
  349. struct MsgPort *replyPort;
  350. {
  351.     struct MsgPort *rexxport;
  352.  
  353.     Forbid();
  354.  
  355.     if (rexxport = FindPort(port)) {
  356.  
  357.         struct RexxMsg *rexxMsg, *answer;
  358.  
  359.         if (rexxMsg = CreateRexxMsg(replyPort, NULL, NULL)) {
  360.  
  361.             if (rexxMsg->rm_Args[0] = CreateArgstring(cmd, strlen(cmd))) {
  362.  
  363.                 static ULONG result;
  364.  
  365.                 rexxMsg->rm_Action = RXCOMM | RXFF_RESULT;
  366.  
  367.                 PutMsg(rexxport, &rexxMsg->rm_Node);
  368.  
  369.                 do {
  370.                     
  371.                     WaitPort(replyPort);
  372.  
  373.                     if (answer = (struct RexxMsg *)GetMsg(replyPort))
  374.                         result = answer->rm_Result1;
  375.  
  376.                 } while (!answer);
  377.  
  378.                 Permit();
  379.  
  380.                 if (answer->rm_Result1 == RC_OK) {
  381.  
  382.                     if (answer->rm_Result2) {
  383.  
  384.                         if (buffer)
  385.                             strcpy(buffer, (char *)answer->rm_Result2);
  386.  
  387.                         DeleteArgstring((char *)answer->rm_Result2);
  388.                     }
  389.                 }
  390.  
  391.                 DeleteArgstring((char *)ARG0(answer));
  392.  
  393.                 DeleteRexxMsg(answer);
  394.  
  395.                 return(&result);
  396.             }
  397.         }
  398.     }
  399.  
  400.     Permit();
  401.  
  402.     return(NULL);
  403. }
  404.  
  405. ///
  406.